﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Windows.Input;
using VisualWip.Core;
using VisualWip.Core.Columns;
using VisualWip.Core.Interfaces;
using VisualWip.Core.Utils;

namespace VisualWip.PresentationModel
{
    public class WindowViewModel : INotifyPropertyChanged
    {
        private readonly Application _application;
        private readonly IViewModelFactory _viewModelFactory;
        private readonly Window _window;
        private readonly IWindowManager _windowManager;
        private RelayCommand _closeCommand;
        private RelayCommand _deleteCommand;
        private RelayCommand _showCommand;

        public WindowViewModel(Application application, Window window, IWindowManager windowManager,
                               IViewModelFactory viewModelFactory, IZoomManager zoomManager,
                               IBoardRecorder boardRecorder)
        {
            _window = window;
            _windowManager = windowManager;
            _viewModelFactory = viewModelFactory;
            _application = application;
            _application.PropertyChanged += ApplicationPropertyChanged;
            _window.WindowColumns.CollectionChanged += ColumnsCollectionChanged;

            boardRecorder.RecordingName = _window.WindowName;
            Board = new BoardViewModel(application, zoomManager, boardRecorder);
        }


        protected Application Application
        {
            get { return _application; }
        }

        protected IViewModelFactory ViewModelFactory
        {
            get { return _viewModelFactory; }
        }

        public Window Window
        {
            get { return _window; }
        }

        public string WindowName
        {
            get { return _window.WindowName; }
        }

        public BoardViewModel Board { get; private set; }

        public ObservableCollection<WindowViewModel> WindowViewModels
        {
            get { return _windowManager.WindowViewModels; }
        }

        public ICommand ShowCommand
        {
            get
            {
                if (_showCommand == null)
                {
                    _showCommand = new RelayCommand(param => _windowManager.Show(this));
                }
                return _showCommand;
            }
        }

        public ICommand DeleteCommand
        {
            get
            {
                if (_deleteCommand == null)
                {
                    _deleteCommand = new RelayCommand(param => _windowManager.Delete(this));
                }
                return _deleteCommand;
            }
        }

        public ICommand CloseCommand
        {
            get
            {
                if (_closeCommand == null)
                {
                    _closeCommand = new RelayCommand(param => _windowManager.Close(this));
                }
                return _closeCommand;
            }
        }

        public bool IsOpen { get; set; }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        private void ColumnsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (Column newItem in e.NewItems)
                {
                    if (IsForThisWindow(newItem))
                        Board.ColumnViewModels.Add(_viewModelFactory.CreateViewModel<ColumnViewModelBase>(newItem));
                }
                OnPropertyChanged(this, () => Board);
            }
            else
            {
                Board.ColumnViewModels.Clear();
                foreach (Column column in _window.WindowColumns)
                {
                    Board.ColumnViewModels.Add(_viewModelFactory.CreateViewModel<ColumnViewModelBase>(column));
                }
                OnPropertyChanged(this, () => Board);
            }
        }

        private bool IsForThisWindow(Column newItem)
        {
            return newItem.WindowName == _window.WindowName;
        }

        protected virtual void ApplicationPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
        }


        protected void OnPropertyChanged<T>(object sender, Expression<Func<T>> property)
        {
            PropertyHelper.OnPropertyChanged(sender, PropertyChanged, property);
        }
    }
}